home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
x11
/
rpg
/
crossfir.92
/
crossfir
/
crossfire-0.92.5
/
common
/
recipe.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-07-24
|
8KB
|
334 lines
/* Basic stuff for use with the alchemy code. Clearly some of this stuff
* could go into server/alchemy, but I left it here just in case it proves
* more generally useful.
*
* Nov 1995 - file created by b.t. thomas@astro.psu.edu
*/
/* Our definition of 'formula' is any product of an alchemical process.
* Ingredients are just comma delimited list of archetype (or object)
* names.
*/
/* Example 'formula' entry in libdir/formulae:
* Object transparency
* chance 10
* ingred dust of beholdereye,gem
* arch potion_generic
*/
#include <global.h>
#include <object.h>
#include <ctype.h>
static recipelist *formulalist;
static recipelist *init_recipelist() {
recipelist *tl = (recipelist *) malloc(sizeof(recipelist));
if(tl==NULL)
fatal(OUT_OF_MEMORY);
tl->total_chance=0;
tl->number=0;
tl->items=NULL;
tl->next=NULL;
return tl;
}
recipe *get_empty_formula() {
recipe *t = (recipe *) malloc(sizeof(recipe));
if(t==NULL)
fatal(OUT_OF_MEMORY);
t->chance = 0;
t->index = 0;
t->transmute = 0;
t->title = NULL;
t->arch_name = NULL;
t->ingred = NULL;
t->next=NULL;
return t;
}
/* get_formulalist() - returns pointer to the formula list */
recipelist * get_formulalist ( int i ) {
recipelist *fl=formulalist;
int number=i;
while(fl && number>1) {
if(!(fl=fl->next)) break;
number--;
}
return fl;
}
/*
* init_formulae() - Builds up the lists of formula from the file in
* the libdir. -b.t.
*/
void init_formulae() {
static int has_been_done=0;
FILE *fp;
char filename[MAX_BUF], buf[MAX_BUF], *cp, *next;
recipe *formula=NULL;
recipelist *fl=init_recipelist();
linked_char *tmp;
int value, comp;
if(!formulalist) formulalist = fl;
if (has_been_done) return;
else has_been_done = 1;
LOG(llevDebug, "Reading alchemical formulae...");
sprintf(filename, "%s/formulae", LibDir);
if ((fp = open_and_uncompress(filename, 0, &comp)) == NULL) {
LOG(llevError, "Can't open %s.\n", filename);
return;
}
while (fgets(buf, MAX_BUF, fp)!=NULL) {
if (*buf=='#') continue;
if((cp=strchr(buf,'\n'))!=NULL)
*cp='\0';
cp=buf;
while(*cp==' ') /* Skip blanks */
cp++;
if (!strncmp(cp, "Object", 6)) {
formula=get_empty_formula();
formula->title = add_string(strchr(cp,' ') + 1);
}
else if (sscanf(cp, "trans %d", &value)) {
formula->transmute = (uint16) value;
}
else if (sscanf(cp, "chance %d", &value)) {
formula->chance = (uint16) value;
}
else if (!strncmp(cp, "ingred",6)) {
int numb_ingred = 1;
cp = strchr(cp,' ') + 1;
do {
if ((next=strchr(cp,','))!=NULL)
{*(next++) = '\0'; numb_ingred++;}
tmp = (linked_char*) malloc(sizeof(linked_char));
tmp->name = add_string(cp);
tmp->next = formula->ingred;
formula->ingred = tmp;
/* each ingredient's ASCII value is coadded. Later on this
* value will be used allow us to search the formula lists
* quickly for the right recipe.
*/
formula->index += strtoint(cp);
} while ((cp=next)!=NULL);
/* now find the correct (# of ingred ordered) formulalist */
fl=formulalist;
while(numb_ingred!=1) {
if(!fl->next)
fl->next = init_recipelist();
fl = fl->next;
numb_ingred--;
}
fl->total_chance += formula->chance;
fl->number++;
formula->next = fl->items;
fl->items = formula;
} else if (!strncmp(cp, "arch",4)) {
formula->arch_name = add_string(strchr(cp,' ')+1);
(void) check_recipe(formula);
} else
LOG(llevError,"Unknown input in file %s: %s\n", filename, buf);
}
close_and_delete(fp, comp);
#ifdef DUMP_SWITCHES
if (dump_monsters == 7) {
dump_alchemy();
exit(0);
}
if (dump_monsters == 8) {
dump_prod_val_vs_cost();
exit(0);
}
#endif
}
/* Borrowed (again) from the artifacts code for this */
void dump_alchemy( void ) {
recipelist *fl=formulalist;
recipe *formula=NULL;
linked_char *next;
int num_ingred=1;
fprintf(logfile, "\n");
while(fl) {
fprintf(logfile, "\n Formulae with %d ingredient%s %d Formulae with total_chance=%d\n",
num_ingred, num_ingred>1?"s.":".",fl->number,fl->total_chance);
for (formula=fl->items; formula!=NULL; formula=formula->next) {
artifact *art=NULL;
archetype *at=NULL;
char buf[MAX_BUF], *string;
string=strtok(formula->arch_name,",");
while(string) {
if((at=find_archetype(string))!=NULL) {
art = locate_recipe_artifact(formula);
if (!art && strcmp(formula->title,"NONE"))
LOG(llevError,"Formula %s has no artifact\n",formula->title);
else {
if(strcmp(formula->title,"NONE"))
sprintf(buf,"%s of %s",string,formula->title);
else
sprintf(buf,"%s",string);
fprintf(logfile,"%-30s(%d) bookchance %3d ",buf,formula->index,
formula->chance);
fprintf(logfile,"\n");
if (formula->ingred !=NULL) {
int nval=0,tval=0;
fprintf(logfile,"\tIngred: ");
for (next=formula->ingred; next!=NULL; next=next->next) {
if(nval!=0) fprintf(logfile,",");
fprintf(logfile,"%s(%d)",next->name,(nval=strtoint(next->name)));
tval += nval;
}
fprintf(logfile,"\n");
if(tval!=formula->index) fprintf(logfile, "WARNING:ingredient list and formula values not equal.\n");
}
}
} else
LOG(llevError,"Can't find archetype:%s for formula %s\n", string,
formula->title);
string = strtok(NULL,",");
}
}
fprintf(logfile,"\n");
fl = fl->next;
num_ingred++;
}
}
void dump_prod_val_vs_cost( void ) {
}
recipe *get_first_recipe() {
recipelist *fl=formulalist;
recipe *formula=fl->items;
return formula;
}
char * ingred_name (char *name) {
char *cp=name;
if(atoi(cp)) cp = strchr(cp,' ') + 1;
return cp;
}
/* strtoint() - we use this to convert buf into an integer
* equal to the coadded sum of the (lowercase) character
* ASCII values in buf (times prepended integers).
*/
int strtoint (char *buf) {
char *cp = ingred_name(buf);
int val=0, len=strlen(cp), mult=numb_ingred(buf);
while (len) {
val += tolower(*cp);
cp++; len--;
}
return val*mult;
}
/* check_recipe() - makes sure we actually have the requested artifact
* and archetype. */
int check_recipe(recipe *rp) {
archetype *at;
if((at=find_archetype(rp->arch_name))!=NULL) {
artifact *art=locate_recipe_artifact(rp);
if (!art && strcmp(rp->title,"NONE")) {
LOG(llevError,"\n WARNING: Formula %s of %s has no artifact.\n",
rp->arch_name,rp->title);
return 0;
}
} else {
LOG(llevError,"\n WARNING: Can't find archetype:%s for formula:%s\n",
rp->arch_name,rp->title);
return 0;
}
return 1;
}
artifact * locate_recipe_artifact(recipe *rp) {
object *item=get_archetype(rp->arch_name);
artifactlist *at=NULL;
artifact *art=NULL;
if(!item) return (artifact *) NULL;
if((at=find_artifactlist(item->type)))
for(art=at->items;art;art=art->next)
if(!strcmp(art->item->name,rp->title)) break;
free_object(item);
return art;
}
int numb_ingred (char *buf) {
int numb;
if((numb=atoi(buf))) return numb;
else return 1;
}
recipelist * get_random_recipelist ( void ) {
recipelist *fl=NULL;
int number=0,roll=0;
/* first, determine # of recipelist we have */
for(fl=get_formulalist(1);fl;fl=fl->next) number++;
/* now, randomly choose one */
if(number>0) roll=RANDOM()%number;
fl=get_formulalist(1);
while(roll && fl) {
if(fl->next) fl = fl->next;
else break;
roll--;
}
if(!fl) /* failed! */
LOG(llevError,"get_random_recipelist(): no recipelists found!\n");
else if(fl->total_chance==0) fl=get_random_recipelist();
return fl;
}
recipe * get_random_recipe ( recipelist *rpl ) {
recipelist *fl=rpl;
recipe *rp=NULL;
int r=0;
/* looks like we have to choose a random one */
if(fl==NULL) if((fl=get_random_recipelist())==NULL) return rp;
r=RANDOM()%fl->total_chance;
for (rp=fl->items;rp;rp=rp->next) {
r -= rp->chance;
if (r<0) break;
}
return rp;
}